/*
ont-space - The ontology-based resource metadata repository
Copyright (c) 2006-2008, Information Eng. Research Unit - Univ. of Alcalá
http://www.cc.uah.es/ie
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.ontspace.dc.owl;

import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.Ontology;
import com.hp.hpl.jena.ontology.Ontology.*;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import java.net.URISyntaxException;
import java.net.URI;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.ontspace.dc.DCQueryManager;
import org.ontspace.owl.MetadataRepositoryImpl;
import org.ontspace.owl.QueryManagerImpl;
import org.ontspace.MetadataRecordReference;
import org.ontspace.owl.MetadataRecordReferenceImpl;

public class DCQueryManagerImpl extends QueryManagerImpl
        implements DCQueryManager {

    private static MetadataRepositoryImpl _rep;
    private static List<Ontology> _onts =
            new ArrayList<Ontology>();
    private List<URI> _uriList;
    private String _nsName =
            "http://www.cc.uah.es/ie/ont/dc-ospace";
    private OntModel _OntModel;

    /** 
     * Creates a new instance of DCQueryManagerImpl
     */
    public DCQueryManagerImpl(MetadataRepositoryImpl rep, HashMap params)
            throws ClassNotFoundException, NoSuchMethodException {
        super(rep);
        _rep =
                rep;
        this._uriList =
                new ArrayList<URI>();
        addRequiredOntologies(params);

    }

    /**
     * Adds the required ontology to the ontologies' list
     * @param ont Ontology to be added into the list
     */
    @Override
    public void addOntologyRef(Ontology ont) {
        if (ont != null) {
            _onts.add(ont);
        }
    }

    /**
     * Adds the required ontologies' URI to the object
     * @param params uri params
     */
    private void addRequiredOntologies(HashMap params) {
        String ontologyUri;
        int i =
                1;
        boolean finished =
                false;
        while (!finished) {
            String paramName =
                    "uri" + i++;
            ontologyUri =
                    (String) params.get(paramName);
            if (ontologyUri != null) {
                try {
                    this._uriList.add(new URI(ontologyUri));
                } catch (URISyntaxException ex) {
                    Logger.getLogger(QueryManagerImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                }
            } else {
                finished =
                        true;
            }
        }
    }

    /**
     * Gets a list with the URIs of the ontologies required by the query manager
     * @return A list whith the USIs of the required ontologies
     */
    @Override
    public List<URI> getRequiredOntologies() {
        return this._uriList;
    }

    /**
     * Gets the ontology model asociated to queryManager
     * @return the ontology model
     */
    public OntModel getOntologyModel() {
        OntModel ontmodel =
                null;

        for (int i =
                0; i < _onts.size(); i++) {
            Ontology ont =
                    _onts.get(i);

            System.out.println(ont.getNameSpace() + ont.getLocalName());
            String ns =
                    ont.getNameSpace() + ont.getLocalName();
            if (ns.compareTo(_nsName) == 0) {
                ontmodel =
                        ont.getOntModel();

            }
        }
        return ontmodel;
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param contributor the contributor to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByContributor(String contributor) {


        return this.queryGeneralAttribute("contributor", contributor);

    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param format the format to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByFormat(String format) {

        return this.queryGeneralAttribute("format", format);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param rights the rights to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByRights(String rights) {

        return this.queryGeneralAttribute("rights", rights);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param coverage the coverage to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByCoverage(String coverage) {

        return this.queryGeneralAttribute("converage", coverage);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param identifier the identifier to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByIdentifier(String identifier) {

        return this.queryGeneralAttribute("identifier", identifier);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param source the source to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCBySource(String source) {

        return this.queryGeneralAttribute("source", source);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param creator the creator to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByCreator(String creator) {
        return this.queryGeneralAttribute("creator", creator);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param language the language to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByLanguage(String language) {
        return this.queryGeneralAttribute("language", language);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param subject the subject to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCBySubject(String subject) {

        return this.queryGeneralAttribute("subject", subject);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param date the date to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByDate(String date) {

        return this.queryGeneralAttribute("date", date);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param publisher the publisher to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByPublisher(String publisher) {

        return this.queryGeneralAttribute("publisher", publisher);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param title the title to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByTitle(String title) {

        return this.queryGeneralAttribute("title", title);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param description the description to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByDescription(String description) {
        return this.queryGeneralAttribute("description", description);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param relation the relation to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByRelation(String relation) {

        return this.queryGeneralAttribute("relation", relation);
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param type the type to search
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public DCQueryResultImpl queryDCByType(String type) {

        return this.queryGeneralAttribute("type", type);
    }

    /**
     * Launches a query for a general attribute in the ontology
     * @param elementType name of the element attribute
     * @param valueAttribute Attribute value
     * @return DCQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    private DCQueryResultImpl queryGeneralAttribute(String elementType,
            String valueAttribute) {

        if (_OntModel == null) {
            _OntModel =
                    this.getOntologyModel();
        }

        DCQueryResultImpl queryResult =
                new DCQueryResultImpl();
        Set<MetadataRecordReference> instancesR =
                new HashSet<MetadataRecordReference>();


        OntClass dc =
                _OntModel.getOntClass(_nsName + "#Resource");

        ExtendedIterator dcInstances =
                dc.listInstances();

        while (dcInstances.hasNext()) {
            Resource dcInstance =
                    (Resource) dcInstances.next();

            //get properties
            Property element =
                    _OntModel.getProperty(_nsName + "#" + elementType);

            StmtIterator elem =
                    dcInstance.listProperties(element);

            while (elem.hasNext()) {
                Statement object =
                        elem.nextStatement();
                String instance =
                        object.getString().toString().replace("\n", " ");

                if (instance.compareTo(valueAttribute) == 0) {

                    MetadataRecordReference mrr =
                            new MetadataRecordReferenceImpl(_rep.getRepositoryURI(),
                            dcInstance.getLocalName());
                    if (!queryResult.getMetadataRecordReference().contains(mrr)) {
                        queryResult.getMetadataRecordReference().add(mrr);
                    }
                }
            }



        }

        return queryResult;

    }
}

